﻿using System;
using System.Diagnostics.Contracts;
using System.IO;
using System.Text;

namespace OpenLS.Spreadsheet.Formats.Biff.Records
{
    internal struct ShortXLUnicodeString : IXLString
    {
        public override string ToString()
        {
            return string.Format("{0}({1})", _value, _doubleByte);
        }
        public void Write (BiffWriterWorkbookContext context, bool isDoubleByte)
    {
            this._doubleByte = isDoubleByte;
            Write(context);
    }

        public void Write(BiffWriterWorkbookContext writer)
        {
            Write(writer.Writer);
        }
        public void Write(BinaryWriter writer)
        {
            Contract.Ensures(writer.BaseStream.Position == Contract.OldValue(writer.BaseStream.Position) + ByteLength);

            writer.Write((byte)_value.Length);
            byte b = (byte)(_doubleByte ? 1 : 0);
            writer.Write(b);
            writer.Write(Encoding.GetBytes(_value));

        }

        public void Read(BinaryReader reader)
        {
            Contract.Ensures(reader.BaseStream.Position == Contract.OldValue(reader.BaseStream.Position) + ByteLength);
            byte count = reader.ReadByte();
            _doubleByte = reader.ReadByte() != 0;
            if (!_doubleByte)
            {
                byte[] bytes = reader.ReadBytes(count);
                _value = Encoding.GetString(bytes);
            }
            else
            {
                byte[] bytes = reader.ReadBytes(count*2);
                _value = Encoding.GetString(bytes);
            }
        }
        public int ByteLength
        {
            get { return 1 + 1 + this.Encoding.GetByteCount(_value); }
        }

        private Encoding Encoding    
        {
            get { if (this._doubleByte) return XlEncodings.TwoByteEncoding;
                return XlEncodings.OneByteEncoding;
            }
        }

        private string _value;
        private bool _doubleByte;
        public static explicit operator string(ShortXLUnicodeString value)
        {
            return value._value;
        }
        public static explicit operator ShortXLUnicodeString(string value)
        {
            Contract.Requires(value != null);
            Contract.Ensures(Contract.Result<ShortXLUnicodeString>()._value != null);
            return new ShortXLUnicodeString { _value = value };
        }
    }
}